﻿using Polly;
using Polly.CircuitBreaker;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common
{
    public class AdvancedCircuitBreaker : DemoBase
    {
        public override string DemoName => "Polly-Advanced CircuitBreaker Demo";

        public override void RunDemo()
        {
            base.Init();

            int runTimes = 50;
            int minimumThroughput = 5;
            int durationOfBreak = 5;
            int samplingDuration = 5;


            var policy = Policy
                .Handle<Exception>()
                .AdvancedCircuitBreaker(
                failureThreshold: 0.5,                       //失败率达到50%才熔断
                minimumThroughput: minimumThroughput,        //最多调用多少次
                samplingDuration: TimeSpan.FromSeconds(samplingDuration),   //评估故障率的时间间隔的持续时间
                durationOfBreak: TimeSpan.FromSeconds(durationOfBreak),    //熔断时间
                onBreak: (ex, breakDelay) =>                 //熔断器打开时触发事件
                {
                    PrintErrorLog($"进入熔断状态 熔断时长：{breakDelay} 错误信息：{ex.Message}");
                },
                onHalfOpen: () =>                           //熔断器进入半打开状态触发事件
                {
                    PrintSuccessLog($"进入HalfOpen状态");
                },
                onReset: () =>                              //熔断器关闭状态触发事件
                {
                    PrintSuccessLog("熔断器关闭");
                }
                );

            for (int i = 1; i <= runTimes; i++)
            {
                try
                {
                    policy.Execute(RequestFromWeb);
                }
                catch (BrokenCircuitException e)
                {
                    PrintLog($"熔断触发{nameof(BrokenCircuitException)}异常");
                }
                catch (Exception e)
                {
                    PrintLog($"异常：{e.GetType().Name},{e.Message}");
                }
                finally
                {
                    Thread.Sleep(500);
                }
            }
        }

        private void RequestFromWeb()
        {
            if (new Random().Next(10) < 5)
            {
                throw new Exception("调用方法内部异常");
            }
            else
            {
                PrintSuccessLog("内部方法执行成功");
            }
        }

    }
}
